# -*- coding: utf-8 -*-
# FileName:     custom_module.py
# time:         23/2/1 001 下午 10:12
# Author:       Zhou Hang
# Description:  I don't want to write
from enum import Enum

from PyQt5 import QtGui, QtCore
from PyQt5.QtCore import Qt, QRectF, QRect, pyqtSignal, QEvent
from PyQt5.QtGui import QColor, QPainter, QPen, QBrush
from PyQt5.QtWidgets import QWidget
from selenium.webdriver.common.print_page_options import Orientation

scHandleSideLength = 11
scSliderBarHeight = 5
scLeftRightMargin = 1


class Option(Enum):
    NoHandle = 1,
    LeftHandle = 2,
    RightHandle = 3,
    DoubleHandles = 4


# 双向滑轨编写
class RangeSlider(QWidget):
    lowerValueChanged = pyqtSignal(int)
    upperValueChanged = pyqtSignal(int)
    rangeChanged = pyqtSignal(int, int)

    def __init__(self, parent=None, ori=Qt.Horizontal, t=Option.DoubleHandles):
        super(RangeSlider, self).__init__(parent)
        self.mMinimum = 0
        self.mMaximum = 100
        self.mLowerValue = 0
        self.mUpperValue = 100
        self.mFirstHandlePressed = False
        self.mSecondHandlePressed = False
        self.mInterval = self.mMaximum - self.mMinimum
        self.mBackgroudColorEnabled = QColor(0x1E, 0x90, 0xFF)
        self.mBackgroudColorDisabled = Qt.darkGray
        self.mBackgroudColor = self.mBackgroudColorEnabled
        self.orientation = ori
        self.type = t
        self.setMouseTracking(True)

    def paintEvent(self, a0: QtGui.QPaintEvent) -> None:
        painter = QPainter()
        painter.begin(self)
        if self.orientation == Qt.Horizontal:
            backgroundRect = QRectF(scLeftRightMargin, (self.height() - scSliderBarHeight) / 2,
                                    self.width() - scLeftRightMargin * 2, scSliderBarHeight)
        else:
            backgroundRect = QRectF((self.width() - scSliderBarHeight) / 2, scLeftRightMargin,
                                    scSliderBarHeight, self.height() - scLeftRightMargin * 2)
        pen = QPen(Qt.gray, 0.8)
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Qt4CompatiblePainting)

        backgroundBrush = QBrush(QColor(0xD0, 0xD0, 0xD0))
        painter.setBrush(backgroundBrush)
        painter.drawRoundedRect(backgroundRect, 1, 1)

        # First value handle rect
        pen.setColor(Qt.darkGray)
        pen.setWidth(0.5)
        painter.setPen(pen)
        painter.setRenderHint(QPainter.Antialiasing)
        handleBrush = QBrush(QColor(0xFA, 0xFA, 0xFA))
        painter.setBrush(handleBrush)
        leftHandleRect = self.firstHandleRect()
        if self.type == Option.LeftHandle:
            painter.drawRoundedRect(leftHandleRect, 2, 2)

        # Second value handle rect
        rightHandleRect = self.secondHandleRect()
        if self.type == Option.RightHandle:
            painter.drawRoundedRect(rightHandleRect, 2, 2)

        # Handles
        painter.setRenderHint(QPainter.Antialiasing, False)
        selectedRect = QRectF(backgroundRect)
        if self.orientation == Qt.Horizontal:
            selectedRect.setLeft((leftHandleRect.right() if self.type == Option.LeftHandle else leftHandleRect.left()) + 0.5)
            selectedRect.setRight((rightHandleRect.left() if self.type == Option.RightHandle else rightHandleRect.right()) - 0.5)
        else:
            selectedRect.setTop((leftHandleRect.bottom() if self.type == Option.LeftHandle else leftHandleRect.top()) + 0.5)
            selectedRect.setBottom((rightHandleRect.top() if self.type == Option.RightHandle else rightHandleRect.bottom()) - 0.5)
        selectedBrush = QBrush(self.mBackgroudColor)
        painter.setBrush(selectedBrush)
        painter.drawRect(selectedRect)

        painter.end()

    def firstHandleRect(self) -> QRectF:
        percentage = (self.mLowerValue - self.mMinimum) // self.mInterval
        return self.handleRect(percentage * self.validLength() + scLeftRightMargin)

    def secondHandleRect(self) -> QRectF:
        percentage = (self.mUpperValue - self.mMinimum) // self.mInterval
        return self.handleRect(percentage * self.validLength() + scLeftRightMargin +
                               scHandleSideLength if self.type == Option.LeftHandle else 0)

    def handleRect(self, aValue: int) -> QRectF:
        if self.orientation == Qt.Horizontal:
            return QRect(aValue, (self.height() - scHandleSideLength) / 2,
                         scHandleSideLength, scHandleSideLength)
        else:
            return QRect((self.width() - scHandleSideLength) / 2,
                         aValue, scHandleSideLength, scHandleSideLength)

    def validLength(self) -> int:
        _len = self.width() if self.orientation == Qt.Horizontal else self.height()
        _t = 2 if self.type == Option.DoubleHandles else 1
        return _len - scLeftRightMargin * 2 - scHandleSideLength * _t

    def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
        if a0.buttons() & Qt.LeftButton:
            posCheck = a0.pos().y() if self.orientation == Qt.Horizontal else a0.pos().x()
            posMax = self.height() if self.orientation == Qt.Horizontal else self.width()
            posValue = a0.pos().x() if self.orientation == Qt.Horizontal else a0.pos().y()
            firstHandleRectPosValue = self.firstHandleRect().x() if self.orientation == Qt.Horizontal else self.firstHandleRect().y()
            secondHandleRectPosValue = self.secondHandleRect().x() if self.orientation == Qt.Horizontal else self.secondHandleRect().y()

            mSecondHandlePressed = self.secondHandleRect().contains(a0.pos())
            mFirstHandlePressed = not self.mSecondHandlePressed and self.firstHandleRect().contains(a0.pos())

            if mFirstHandlePressed:
                self.mDelta = posValue - (firstHandleRectPosValue + scHandleSideLength // 2)
            elif mSecondHandlePressed:
                self.mDelta = posValue - (secondHandleRectPosValue + scHandleSideLength // 2)

            if 2 <= posCheck <= posMax - 2:
                step = 1 if (self.mInterval // 10) < 1 else self.mInterval // 10
                if posValue < firstHandleRectPosValue:
                    self.setLowerValue(self.mLowerValue - step)
                elif posValue > (firstHandleRectPosValue + scHandleSideLength) or not self.type == Option.LeftHandle and (posValue < secondHandleRectPosValue or not self.type == Option.RightHandle):
                    if self.type == Option.DoubleHandles:
                        if posValue - (firstHandleRectPosValue + scHandleSideLength) < (secondHandleRectPosValue - (firstHandleRectPosValue + scHandleSideLength)) // 2:
                            self.setLowerValue(
                                self.mLowerValue + step if self.mLowerValue + step < self.mUpperValue else self.mUpperValue)
                        else:
                            self.setUpperValue(
                                self.mUpperValue + step if self.mUpperValue - step > self.mLowerValue else self.mLowerValue)
                    elif self.type == Option.LeftHandle:
                        self.setLowerValue(
                            self.mLowerValue + step if self.mLowerValue + step < self.mUpperValue else self.mUpperValue)
                    elif self.type == Option.RightHandle:
                        self.setUpperValue(
                            self.mUpperValue + step if self.mUpperValue - step > self.mLowerValue else self.mLowerValue)
                elif posValue > secondHandleRectPosValue + scHandleSideLength:
                    self.setUpperValue(self.mUpperValue + step)

    def mouseMoveEvent(self, a0: QtGui.QMouseEvent) -> None:
        posValue = a0.pos().x() if self.orientation == Qt.Horizontal else a0.pos().y()
        firstHandleRectPosValue = self.firstHandleRect().x() if self.orientation == Qt.Horizontal else self.firstHandleRect().y()
        secondHandleRectPosValue = self.secondHandleRect().x() if self.orientation == Qt.Horizontal else self.secondHandleRect().y()
        if self.mFirstHandlePressed and self.type == Option.LeftHandle:
            if posValue - self.mDelta + scHandleSideLength // 2 <= secondHandleRectPosValue:
                self.setLowerValue((posValue - self.mDelta - scLeftRightMargin - scHandleSideLength // 2) / self.validLength() * self.mInterval + self.mMinimum)
            else:
                self.setLowerValue(self.mUpperValue)
        elif self.mFirstHandlePressed and self.type == Option.RightHandle:
            if firstHandleRectPosValue + scHandleSideLength * (1.5 if self.type == Option.DoubleHandles else 0.5) <= posValue - self.mDelta:
                self.setUpperValue((posValue - self.mDelta - scLeftRightMargin - scHandleSideLength // 2 - (scHandleSideLength if self.type == Option.DoubleHandles else 0)) / self.validLength() * self.mInterval + self.mMinimum)
            else:
                self.setUpperValue(self.mLowerValue)

    def mouseReleaseEvent(self, a0: QtGui.QMouseEvent) -> None:
        self.mFirstHandlePressed = False
        self.mSecondHandlePressed = False

    def changeEvent(self, a0: QtCore.QEvent) -> None:
        if a0.type() == QEvent.EnabledChange:
            if self.isEnabled():
                self.mBackgroudColor = self.mBackgroudColorEnabled
            else:
                self.mBackgroudColor = self.mBackgroudColorDisabled
            self.update()

    def setLowerValue(self, aLowerValue: int):
        if aLowerValue > self.mMaximum:
            aLowerValue = self.mMaximum
        if aLowerValue < self.mMinimum:
            aLowerValue = self.mMinimum
            self.mLowerValue = aLowerValue

        self.lowerValueChanged.emit(self.mLowerValue)
        self.update()

    def setUpperValue(self, aUpperValue: int):
        if aUpperValue > self.mMaximum:
            aUpperValue = self.mMaximum
        if aUpperValue < self.mMinimum:
            aUpperValue = self.mMinimum

        self.mUpperValue = aUpperValue
        self.upperValueChanged.emit(self.mUpperValue)
        self.update()


def main():
    pass


if __name__ == "__main__":
    main()
